local CONST = {NUM_HANDFULL=14, MAX_INDEX=34, PAI_TOTAL = 136, MASK_COLOR=0xF0, MASK_VALUE=0x0F}
local ACTIONTYPE={WIK_HU=1, WIK_PENG=2, WIK_ANGANG=3, WIK_JIAGANG=4, WIK_JIEGANG=5}
local HUTYPE = {HT_NULL=0, HT_PINGHU=1, HT_PENGPENGHU=0x2, HT_QIXIAODUI=0x4, HT_QIDADUI=0x8, HT_HAOQI=0xF, HT_CHAOHAOQI=0xF0, HT_SHISANYAO=0x10}
local FAN = {QINGYISE=0x0001, PENGPENGHU=0x0002, SHISANYAO=0x0800, DUIZI=0x1000}

function DeepCopy( obj )	
	local InTable = {};
	local function Func(obj)
		if type(obj) ~= "table" then   --判断表中是否有表
			return obj;
		end
		local NewTable = {};  --定义一个新表
		InTable[obj] = NewTable;  --若表中有表，则先把表给InTable，再用NewTable去接收内嵌的表
		for k,v in pairs(obj) do  --把旧表的key和Value赋给新表
			NewTable[Func(k)] = Func(v);
		end
		return setmetatable(NewTable, getmetatable(obj))--赋值元表
	end
	return Func(obj) --若表中有表，则把内嵌的表也复制了
end

function table.merge( tDest, tSrc , bFilterSame, filed)
	if not tSrc or not tDest then return end
	local i = 1
    for k, v in ipairs( tSrc ) do
		local bFind = false
		if bFilterSame then     --剔重
			if not filed then
				for j = 1, #tDest do if tDest[j] == v then bFind = true end end
			else
				for j = 1, #tDest do if tDest[j][filed] == v[filed] then bFind = true end end
			end
		end
        if not bFind or not bFilterSame then tDest[#tDest + i] = v end
    end
end


local table_mjCardData =
{
	0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,						--万子
	0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,						
	0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,						
	0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,						
	0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,						--索子
	0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,						
	0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,						
	0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,						
	0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,						--同子
	0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,						
	0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,						
	0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,						
	0x31,0x32,0x33,0x34,0x35,0x36,0x37,									--番子
	0x31,0x32,0x33,0x34,0x35,0x36,0x37,									
	0x31,0x32,0x33,0x34,0x35,0x36,0x37,									
	0x31,0x32,0x33,0x34,0x35,0x36,0x37,								   --西北中发白
};


MjLogic = {table_RepertoryCard = {}}

function MjLogic:New (obj)
	obj = obj or {}
	setmetatable(obj, self)
	self.__index = self
	return obj
end

function MjLogic:Init()
	for i = 1, CONST.PAI_TOTAL do 
		self.table_RepertoryCard[i] = table_mjCardData[i]
	end
end

local function randCardLocal(card)
	local tab_RandCard = {}
	local len = #card
	math.randomseed(tostring(os.time()):reverse():sub(1, 7))
	for i = 1, len do
		local r = math.random(1, len - i + 1)
		tab_RandCard[i], card[r] = card[r], card[len - i + 1]
	end
	return tab_RandCard
end


function MjLogic:PaiArrToIndexArr(paiArr)
	local indexArr = {}
	for i = 1, CONST.MAX_INDEX do indexArr[i] = 0 end	
	for i = 1, #paiArr do
		local index = MjLogic:ValToIndex(paiArr[i])
		indexArr[index] = indexArr[index] + 1  
	end
	return indexArr
end

function MjLogic:randCard(count)
	for i = 1, count do
		self.table_RepertoryCard = randCardLocal(self.table_RepertoryCard)
	end
end

function MjLogic:IndexToVal(index)
	local ind = index - 1
	local s, _ = ind//9
	return (s<<4)|(ind%9+1);
end

function MjLogic:ValToIndex(val)
	return ((val&CONST.MASK_COLOR)>>4)*9+(val&CONST.MASK_VALUE)
end

function MjLogic:GetHandCardNum(arrIndex)
	local num = 0
	for i = 1, #arrIndex do 
		--io.write(arrIndex[i], " ")
		num = num + arrIndex[i]
	end
	--io.write("\n")
	return num
end

function MjLogic:AnalysePeng(cardInx, getCardData)
	local index = self:ValToIndex(getCardData)
	if cardIndex[index] > 2 then return true
	else return false end
end

function MjLogic:AnalyseAllAnGang(cardInx)
	local anGang = {}
	for i = 1, #cardInx do
		if cardInx[i] == 4 then
			anGang.cardCard = self:IndexToVal(i)
		end
	end
	return anGang
end

function MjLogic:AnalyseJiaGang(weaveItem, getCardData)
	for i = 1, #weaveItem do
		if weaveItem[i].weaveKind == ACTIONTYPE.WIK_PENG then
			if weaveItem[i].CenterCard == getCardData then
				return {type=ACTIONTYPE.WIK_JIAGANG, cardData=getCardData}
			end
		end
	end
	return nil
end

function MjLogic:AnalyseJieGang(cardIndex, getCardData)
	local index = self:ValToIndex(getCardData)
	if cardIndex[index] == 3 then return true
	else return false end
end

function MjLogic:ProcessSerialPai(tabPai)
	if #tabPai % 3 == 0 then 
		local ret = false 
		if self:ValidPai(tabPai) then ret = 1 end 
		return ret, {}    --3的倍数直接判断
	end
	local tingData = self:CalHuCommonPai(tabPai)
	local bOk = self:ValidPai(tabPai)
	if bOk == nil then  --1,4,7,10,13,单钓一张牌
		if #tingData == 0 then return false 
		else return 0, tingData end
	else
		if #tingData == 0 and not bOk then return false  --2,5,8 
		else  
			local ret = 0
			if bOk then ret = 1 end
		    return ret, tingData 
		end
	end
	return 0, tingData         --1表示不缺,0表示缺一个字才成一句
end

function MjLogic:ValidPai(tabPai, p2)
	if #tabPai == 0 then return true end
	local func = {nil, 
				self.Valid2Pai, 
				self.Valid3Pai,
				nil;
				self.Valid5Pai,
				self.Valid6Pai,
				nil,
				self.Valid8Pai,
				self.Valid9Pai,
				nil,
				self.Valid11Pai,
				self.Valid12Pai,
				nil,
				self.Valid14Pai}
	if func[#tabPai] == nil then return nil end
	local sum = 0
	for i = 1, #tabPai do
		sum = sum + tabPai[i]
	end
	tabPai.d = sum
	return func[#tabPai](self, tabPai)
end

function MjLogic:SplitPai(tabPai, split)
	for k = 1, #split do 
		local card1 = {}
		local card2 = {}
		for i = 1, split[k] do
			table.insert(card1, tabPai[i])
		end
		for i = 1, #tabPai - split[k] do 
			table.insert(card2, tabPai[i + split[k]])
		end
		bOk = (self:ValidPai(card1) and self:ValidPai(card2))
		if bOk then return true end
	end
	return false
end

function MjLogic:SelectSerial3(tabPai, bRev)   --选择连续的不重叠的3个
	local paiSeries1 = {}
	local paiSeries2 = {}
	local b, e, s = 1, #tabPai, 1    --begin,end, step
	if bRev then b, e, s = #tabPai, 1, -1 end
	for i = b, e, s do
		if tabPai[i] ~= paiSeries1[#paiSeries1] and #paiSeries1 < 3 then
			table.insert(paiSeries1, tabPai[i])
		else table.insert(paiSeries2, tabPai[i])
		end
	end
	return paiSeries1, paiSeries2
end

function MjLogic:ValidCommonPai(tabPai, split)   --判断是不是将
	local bOk = false
	bOk = self:SplitPai(tabPai, split)
	if bOk then return true end
	local paiSeries1, paiSeries2 = self:SelectSerial3(tabPai)  --正选
	bOk = self:ValidPai(paiSeries1) and self:ValidPai(paiSeries2)
	if bOk then return true end
	paiSeries1, paiSeries2 = self:SelectSerial3(tabPai, true)  --反选
	bOk = self:ValidPai(paiSeries1) and self:ValidPai(paiSeries2)
	if bOk then return true end
	return false
end

function MjLogic:Valid2Pai(tabPai)   --判断是不是将
	return tabPai[1] == tabPai[2]
end

function MjLogic:Valid3Pai(tabPai)   --判断是不是连续的3个数  例如222,234
	if #tabPai ~= 3 then return false end
	local sum = 0
	for i = 1, #tabPai do 
		sum = sum + tabPai[i]
	end	
	if sum % 3 ~= 0 then return false end
	local av = sum / 3
	if (tabPai[2] ~= av) then return false end
	if tabPai[1] == tabPai[2] and tabPai[2] == tabPai[3] then return true end    
	local bOk = true
	if (tabPai[1] ~= av) then bOk = (bOk and (math.abs((av- tabPai[1]))) == 1) end
	if (tabPai[3] ~= av) then bOk = (bOk and (math.abs((av- tabPai[3]))) == 1) end
	return bOk, false  --不是碰碰
end

function MjLogic:Valid5Pai(tabPai)
	local bOk = false
	local split = {2, 3}
	bOk = self:SplitPai(tabPai, split)
	if bOk then return true end
	local paiSeries1, paiSeries2 = self:SelectSerial3(tabPai)  --计算重叠的23334(即234,33)
	bOk = self:ValidPai(paiSeries1) and self:ValidPai(paiSeries2)
	if bOk then return true end
	return false
end

function MjLogic:Valid6Pai(tabPai)
	local split = {3}
	return self:ValidCommonPai(tabPai, split)
end

function MjLogic:Valid8Pai(tabPai)
	local split = {3, 5}
	return self:ValidCommonPai(tabPai, split)
end

function MjLogic:Valid9Pai(tabPai)
	local split = {3, 6}
	return self:ValidCommonPai(tabPai, split)
end

function MjLogic:Valid11Pai(tabPai)
	local split = {5, 6}
	return self:ValidCommonPai(tabPai, split)
end

function MjLogic:Valid12Pai(tabPai)
	local split = {6, 6}
	return self:ValidCommonPai(tabPai, split)
end

function MjLogic:Valid14Pai(tabPai)
	local split = {6, 8}
	return self:ValidCommonPai(tabPai, split)
end

function MjLogic:CalHuCommonPai(tabPai)
	if #tabPai % 3 == 0 then return {} end
	local min = tabPai[1] - 1
	local max = tabPai[#tabPai] + 1
	if tabPai[1] % 16 == 1 then min = tabPai[1] end
	if tabPai[#tabPai] % 16 == 9 then max = tabPai[#tabPai] end
	local huPai = {}
	local v = min
	repeat
		local tab = DeepCopy(tabPai)
		table.insert(tab, v)
		table.sort(tab)
		if self:ValidPai(tab) then table.insert(huPai, v) end
		v = v + 1
	until v >  max
	return huPai
end

function MjLogic:ValidShouPai(tabWan, tabTiao, tabTong, tabZi)   --听,胡牌时(即13或14张牌)都通用
	local nZi1, nZi2 = 0, 0
	local nZi = 0    --共有多少字牌
	for i = 1, #tabZi do
		if tabZi[i] % 3 == 1 then nZi1 = nZi1 + 1 end
		if tabZi[i] % 3 == 2 then nZi2 = nZi2 + 1 end
		if tabZi[i] > 0 then nZi = nZi + tabZi[i] end
	end
	local nTotal = tabWan.n + tabTiao.n + tabTong.n + nZi
	local nDanTotal = 1
	local nDuiTotal = 2
	if nTotal % 3 == 2 then nDanTotal = 0 nDuiTotal = 1 end
	if nZi1 > nDanTotal then return false end       --单个字超过1个
	if nZi2 > nDuiTotal then return false end       --对子字超过2个
	if nZi1 * nZi2 > 0 then return false end
	
	local tabWTT = {tabWan, tabTiao, tabTong}
	local n1, n2 = 0, 0
	for i = 1, #tabWTT do
		if tabWTT[i].n % 3 == 1 then n1 = n1 + 1 end
		if tabWTT[i].n % 3 == 2 then n2 = n2 + 1 end
	end
	if n1 > nDanTotal then return false end       --单个出现2次以上
	if n2 > nDuiTotal then return false end       --对子个出现3次以上
	if n1 * n2 > 0 then return false end   --单个对子同时出现
	
	if (nZi1 + n1) > nDanTotal then return false end
	if (nZi2 + n2) > nDuiTotal then return false end
	if (nZi1 + n1) * (nZi2 + n2) > 0 then return false end
	return true
end

function MjLogic:ProcessOneColor(tabCur, bCheckHu)    --提取连续的牌并处理
	local wCardIndex = tabCur.w
	if wCardIndex ~= 0 then            --去掉首尾的0
		while (wCardIndex & 1) == 0 do  
			wCardIndex = wCardIndex >> 1
		end
		tabCur.w = wCardIndex
	end
    
    function getN(n)
        local c = 0
        while n > 0 do
          n = n >> 1
          c = c + 1
        end
        return c
    end
    function revN(wCardIndex)
        local c = getN(wCardIndex)
        local r = 0
        while wCardIndex  ~= 0 do    
            if wCardIndex & 1 ~= 0 then r = r + (2 << (c - 2))  end
            c = c - 1
            wCardIndex = wCardIndex >> 1
        end
        return r
    end
    function comps(a,b) return a > b end
    local rWCardIndex = revN(wCardIndex)     --解决123，6不听的bug
    if rWCardIndex < wCardIndex then 
      wCardIndex = rWCardIndex
      tabCur.w = rWCardIndex
      table.sort(tabCur.val, comps)
    end
    
	if tabCur.n == 0 then return 1, {} end
	if tabCur.n == 2 and wCardIndex == 5 then return 0, {tabCur.val[1] + 1} end  --胡卡张
	local tingData = {}
	local nQuan = 1
	local nNotQuan = 0
	local bOk = false
	local indexVal = 0
	local kaZhang = {}
	local wCardIndex2 = wCardIndex
	local paiValTemp = DeepCopy(tabCur.val)
	while wCardIndex2 ~= 0 do    --计算卡张的
		while (wCardIndex2 & 1) == 0 do wCardIndex2 = wCardIndex2 >> 1 end
		if (wCardIndex2 & 7) == 5 then 
			wCardIndex2 = wCardIndex2 - 5
			local k = #tabCur.val - indexVal
			table.insert(paiValTemp, tabCur.val[k] - 1)
			table.sort(paiValTemp)
			if self:ValidPai(paiValTemp) then
				kaZhang[#kaZhang + 1] = tabCur.val[k] - 1
			end
			indexVal = indexVal + 2
			break
		elseif wCardIndex2 & 7 == 7 then
			wCardIndex2 = wCardIndex2 - 7
			indexVal = indexVal + 3
		elseif wCardIndex2 & 3 == 3 then
			wCardIndex2 = wCardIndex2 - 3
			indexVal = indexVal + 2
		else break end		
	end
	if #kaZhang > 1 then return false end
	indexVal = 0
	local n1Or2 = 0    --一个或两个的个数  110011011111
	while wCardIndex ~= 0 do
		local valPai = {}
		while (wCardIndex & 1) == 0 do wCardIndex = wCardIndex >> 1	end
		if (wCardIndex ~= 1) and (wCardIndex & 3) ~= 3 and (wCardIndex & 7) ~= 7 then
			if #kaZhang ~= 1 then  return false                           --11  111或101
			else return 0, kaZhang end
		end 
		local index = {1,2,3,4,5,6,7,8,9,10,11,12,13,14}  --减掉最大的连续数
		for i = #index, 1, -1 do 
			local nIndex = index[i]     --现在去掉了几张
			local v = 2 ^ nIndex - 1  --111,11....
			if (wCardIndex & v == v) then 
				wCardIndex = wCardIndex - v
				indexVal = indexVal + nIndex  --已去掉几张牌
				for j = 1, nIndex do  --去掉的牌组成表,然后判断
					local k = #tabCur.val - indexVal + j
					table.insert(valPai, tabCur.val[k])
				end
				local huPai = {}
				if #valPai <=2 then n1Or2 = n1Or2 + 1 end
				if n1Or2 >= 3 then return false end
				bOk, huPai = self:ProcessSerialPai(valPai)
				if bOk == 0 then nQuan = 0  nNotQuan = nNotQuan + 1 end
				if nNotQuan > 1 then    --有两个不全的,肯定不听
					tingData = {}
					break
				end 
				if bCheckHu then
					 if bOk ~= 1 then   --检测胡的时候,牌不全直接返回
						if #kaZhang ~= 1 then return false
						else return 0, kaZhang end
					end
				end 
				if not bOk then
					if #kaZhang ~= 1 then return false
					else return 0, kaZhang end
				end
				if tabCur.n % 3 ~= 0 then     --只有不是3的倍数才添加,比如1,1,2,2,3,3,4,6,6 按照这个算法会插入1,4但是整体是9张牌,不缺的!!!
					for i = 1, #huPai do table.insert(tingData, huPai[i]) end
				end
				break
			end
		end
	end
	
	if #kaZhang == 1 then 
		table.insert(tingData, kaZhang[1])
	end
	return nQuan, tingData
end

function MjLogic:IsQiDui(cardIndex)
	local num, dan, four = 0, 0, 0
	local ting = 0
	for i = 1, CONST.MAX_INDEX do 
		if cardIndex[i] % 2 == 0 then end 
		if cardIndex[i] % 2 == 1 then dan = dan + 1 end 
		if dan == 1 and ting == 0 then ting = self:IndexToVal(i) 
		elseif dan > 1 then return false end
		if cardIndex[i] > 0 then num = num + cardIndex[i] end
		if cardIndex[i] > 3 then four = four + 1 end
	end
	local hu = {duiNum=four, val={}, fan=FAN.DUIZI}
	table.insert(hu.val, ting)
	if num == 14 or num == 13 then return true, hu end    --胡,听,0,1,2,3,4小对,大队,豪七,超豪七
	return false
end

function MjLogic:IsShiSanYao(cardIndex)
	local dui = 0
	local num = 0
	local ting = 0
	local yaoPai = {}
	for i = 1, CONST.MAX_INDEX do 
		local v = self:IndexToVal(i)
		local bYaoPai = false
		if self:IsYaoPai(v) then table.insert(yaoPai, v)  bYaoPai = true end
		if cardIndex[i] > 0 then
			num = num + cardIndex[i]
			if not bYaoPai then return false end 
		end 
		if cardIndex[i] == 0 then    --某张幺牌没有,那么一定只胡该张幺牌
			if bYaoPai then ting = v end
		end
		if cardIndex[i] > 1 then dui = dui + 1 end
		if dui > 1 then return false end
	end
	local hu = {val = {}, fan = FAN.SHISANYAO}
	if num == 14 then return true end   --胡
	if ting ~= 0 then table.insert(hu.val, ting) 
	else     --听所有幺牌
		hu.val = yaoPai	
	end
	if num == 13 then return true, hu end   --听,0,1,2,3,4小对,大队,豪七,超豪七
end

function MjLogic:OtherHu(cardIndex)
	return false
end

function MjLogic:IsYaoPai(getCard)
	if getCard == 0 then return false
	else
		if getCard & CONST.MASK_VALUE == 0x01 or 
		   getCard & CONST.MASK_VALUE == 0x09 or
		   getCard & CONST.MASK_COLOR == 0x30 then
		   return true
		end
	end
	return false
end

function MjLogic:IsTing(cardIndex, weaveItem, index)
	local numInHand = self:GetHandCardNum(cardIndex)
	if numInHand % 3 ~= 1 then 
		print("In IsTing, HandCardNum Invalid!!! ")
	end
	local tingPaiData = {val = {},type={}}	
	for i = 1, CONST.MAX_INDEX do
		tingPaiData[i] = 0
	end
	local bOk, huPaiData = self:GetTingData(cardIndex)	
	if bOk then 
		local cardIndexTemp = DeepCopy(cardIndex)
		for i = 1, #huPaiData do 
			for j = 1, #huPaiData[i] do
				local index = self:ValToIndex(huPaiData[i][j]) 
				cardIndexTemp[index] = cardIndexTemp[index] + 1 
				local huType = HUTYPE.HT_PINGHU
				if self:IsPengPengHu(cardIndexTemp) then huType = HUTYPE.HT_PENGPENGHU end
				local v = huPaiData[i][j]
				local ind = self:ValToIndex(v)
				if tingPaiData[ind] == 0 then 
					tingPaiData[ind] = 1
					tingPaiData.val[#tingPaiData.val + 1] = v
					tingPaiData.type[#tingPaiData.type + 1] = huType
				end
			end
		end
	end
	
	local otherHu = {}
	if weaveItem == nil or #weaveItem == 0 then 
		local otherHuFcnt = {self.IsQiDui, self.IsShiSanYao, self.OtherHu}
		for i = 1, #otherHuFcnt do
			local bOk, hu = otherHuFcnt[i](self, cardIndex)
			if bOk and hu then
				for j = 1, #hu.val do
					local ind = self:ValToIndex(hu.val[j])
					local v = hu.val[j]
					if tingPaiData[ind] == 0 then
						tingPaiData[ind] = 1
						tingPaiData.val[#tingPaiData.val + 1] = v
						if i == 1 then        --七对
							if hu.duiNum == 0 then tingPaiData.type[#tingPaiData.type + 1] = HUTYPE.HT_QIXIAODUI
							elseif hu.duiNum == 1 then tingPaiData.type[#tingPaiData.type + 1] = HUTYPE.HT_QIDADUI
							elseif hu.duiNum == 2 then tingPaiData.type[#tingPaiData.type + 1] = HUTYPE.HT_HAOQI
							elseif hu.duiNum == 3 then tingPaiData.type[#tingPaiData.type + 1] = HUTYPE.HT_CHAOHAOQI end
						elseif i == 2 then    --十三幺
							tingPaiData.type[#tingPaiData.type + 1] = HUTYPE.HT_SHISANYAO
						end
					end 
				end
			end
		end
	end
	return tingPaiData
end

function MjLogic:IsHu(cardIndex, weaveItem)
	local numInHand = self:GetHandCardNum(cardIndex)
	if numInHand % 3 ~= 2 then 
		print("In IsHu, HandCardNum Invalid!!! ")
	end
	local tabWan, tabTiao, tabTong, tabZi = self:ParsePaiToWTTZ(cardIndex)
	
	if not self:ValidShouPai(tabWan, tabTiao, tabTong, tabZi) then return false end
	
	local bOkRet = false
	local tabWTTZ = {tabWan, tabTiao, tabTong, tabZi}
	bOkRet = self:ProcessOneColor(tabWTTZ[1])
	if bOkRet ~= 1 then return false end
	bOkRet = self:ProcessOneColor(tabWTTZ[2])
	if bOkRet ~= 1 then return false end
	bOkRet = self:ProcessOneColor(tabWTTZ[3])
	if bOkRet ~= 1 then return false end
	
	local fan = self:GetFanWaiFan(cardIndex, weaveItem)
	return true, fan
end

function MjLogic:ParsePaiToWTTZ(cardIndex)
	local tabWan   = {n = 0, d = 0, w = 0, val = {}}
	local tabTiao  = {n = 0, d = 0, w = 0, val = {}}
	local tabTong  = {n = 0, d = 0, w = 0, val = {}}
	local tabZi    = {0,0,0,0,0,0,0}
	local tabWTTZ = {tabWan, tabTiao, tabTong, tabZi}
	for i = 1, CONST.MAX_INDEX do
		local iData = cardIndex[i]
		local v = self:IndexToVal(i)
		local col = (i - 1) // 9 + 1
		if col < 4 then     --万饼条
			for m = 1, iData do table.insert(tabWTTZ[col].val, v) end
			tabWTTZ[col].n = tabWTTZ[col].n + iData
			tabWTTZ[col].d = tabWTTZ[col].d + v * iData
			if tabWTTZ[col].w > 0  then
				tabWTTZ[col].w = tabWTTZ[col].w << math.max(1, iData);      --至少移一位
				tabWTTZ[col].w = tabWTTZ[col].w + ((1 << iData) - 1)
			end
			if iData > 0 and tabWTTZ[col].w == 0 then tabWTTZ[col].w = (1 << iData) - 1	end
		else tabZi[i - 27] = iData end        --字
	end
	return tabWan, tabTiao, tabTong, tabZi
end

function MjLogic:GetFanWaiFan(cardIndex, weaveItem)
	local fan = 0
	if self:IsPengPengHu(cardIndex) then fan = fan | FAN.PENGPENGHU end
	if self:IsQingYiSe(cardIndex, weaveItem) then fan = fan | FAN.QINGYISE end
	return fan
end

function MjLogic:GetTingData(cardIndex, weaveItem)    --缺一张牌的情况
	local tabWan, tabTiao, tabTong, tabZi = self:ParsePaiToWTTZ(cardIndex)
	local tabWTT = {tabWan, tabTiao, tabTong}
	
	local bOk = self:ValidShouPai(tabWan, tabTiao, tabTong, tabZi)    --计算听牌时的手牌
	if not bOk then return false end
	
	local huPaiData = {{},{},{},{}}
	local bOk = {false, false, false} 
	bOk[1], huPaiData[1] = self:ProcessOneColor(tabWTT[1])
	if not bOk[1] then return false end
	local tWangTemp = DeepCopy(tabWan)
	if #huPaiData[1] > 0 then  tWangTemp.n = tWangTemp.n + 1 end
	if not self:ValidShouPai(tWangTemp, tabTiao, tabTong, tabZi) then return false end   --计算胡牌时的手牌,比如前面万有6个是通过的,但是就不能再加一个了
	
	bOk[2], huPaiData[2] = self:ProcessOneColor(tabWTT[2])
	if not bOk[2] then return false end
	local tTiaoTemp = DeepCopy(tabTiao)
	if #huPaiData[2] > 0 then tTiaoTemp.n = tTiaoTemp.n + 1 end
	if not self:ValidShouPai(tabWan, tTiaoTemp, tabTong, tabZi) then return false end
	
	bOk[3], huPaiData[3] = self:ProcessOneColor(tabWTT[3])
	if not bOk[3] then return false end
	local tTongTemp = DeepCopy(tabTong)
	if #huPaiData[3] > 0 then tTongTemp.n = tTongTemp.n + 1 end
	if not self:ValidShouPai(tabWan, tabTiao, tTongTemp, tabZi) then return false end
	
	for i = 1, 3 do
		local index1 = (i + 0) % 3 + 1       --取其他的两个,i == 2,其他那就是3,1
		local index2 = (i + 1) % 3 + 1
		if bOk[i] == 0 then huPaiData[index1] = {} huPaiData[index2] = {} end
	end
	if (bOk[1] + bOk[2] + bOk[3]) < 3 then   --wtt还差牌,就不要计算字牌了
		return true, huPaiData
	else
		local nTabZi = #tabZi
		for i = 1, nTabZi do 
			if tabZi[i] % 3 == 1 then      --考虑到鬼牌,可以有5个东(,...)
				table.insert(huPaiData[4], self:IndexToVal(27 + i))
			elseif tabZi[i] % 3 == 2 then
				table.insert(huPaiData[4], self:IndexToVal(27 + i))
			end
		end
		if huPaiData[4] and #huPaiData[4] > 2 then huPaiData[4] = {} return false end
	end
	
	return true, huPaiData
end

function MjLogic:IsQingYiSe(cardIndex, weaveItem)   --是否为清一色
	local col = 0xFF
	local i = 1
	repeat 
		if cardIndex[i] > 0 then
			if col ~= 0xFF then return false end
			col = self:IndexToVal(i) & CONST.MASK_COLOR
			i = (i // 9 + 1) * 9    --跳到下一个色的范围,有就表示不是清一色
		end
		i = i + 1
	until (i > CONST.MAX_INDEX)
	if weaveItem ~= nil and #weaveItem > 0 then 
		for i = 1, #weaveItem do 
			if weaveItem[i].CenterCard & CONST.MASK_COLOR ~= col then return false end
		end
	end
	return true
end

function MjLogic:IsPengPengHu(cardIndex)
	local double = 0
	for i = 1, #cardIndex do 
		if cardIndex[i] % 3 == 1 then return false end
		if cardIndex[i] % 3 == 2 then double = double + 1 end
		if double > 1 then return false end
	end
	return true
end

function MjLogic:TingGuiPai(guiVal, cardIndex)
	local i,j,m,n = 1,1,1,1
	local it = {34,34,34,34}
	local indexGui = self:ValToIndex(guiVal)
	if indexGui == 0 then return false end
	local guiNum = cardIndex[indexGui]
	if guiNum == 0 then return false end   --没有鬼牌
	cardIndex[indexGui] = cardIndex[indexGui] - guiNum
	for i = 1, guiNum do it[i] = 1 end
	local nTotalTing = 0
	local tingTotal = {}
	for i = 1, CONST.MAX_INDEX do tingTotal[i] = 0 end
	n = it[4]
	repeat
		m = it[3]
		repeat
			j = it[2]
			repeat
				i = it[1]
				repeat
					local iV = MjLogic:IndexToVal(i)
					local jV = MjLogic:IndexToVal(j)
					local mV = MjLogic:IndexToVal(m)
					local nV = MjLogic:IndexToVal(n)
					local cardIndexTemp = DeepCopy(cardIndex)
					if guiNum > 0 then cardIndexTemp[i] = cardIndexTemp[i] + 1 end
					if guiNum > 1 then cardIndexTemp[j] = cardIndexTemp[j] + 1 end
					if guiNum > 2 then cardIndexTemp[m] = cardIndexTemp[m] + 1 end
					if guiNum > 3 then cardIndexTemp[n] = cardIndexTemp[n] + 1 end
					local retTing = MjLogic:IsTing(cardIndexTemp)
					local r = #retTing.val
					if #retTing.val == 0 then j = j + 1  break end  --如果鬼牌1,2,3,4不胡的话,1,2,3,x肯定也不会胡
					for c = 1, #retTing.val do
						local ind = MjLogic:ValToIndex(retTing.val[c])
						if tingTotal[i] == 0 then tingTotal[i] = iV nTotalTing = nTotalTing + 1 end
						if tingTotal[j] == 0 then tingTotal[j] = jV nTotalTing = nTotalTing + 1 end
						if tingTotal[m] == 0 then tingTotal[m] = mV nTotalTing = nTotalTing + 1 end
						if tingTotal[n] == 0 then tingTotal[n] = nV nTotalTing = nTotalTing + 1 end
						if nTotalTing >= 34 then
							i,j,m,n = CONST.MAX_INDEX,CONST.MAX_INDEX,CONST.MAX_INDEX,CONST.MAX_INDEX
							break
						end
						if tingTotal[ind] == 0 then tingTotal[ind] = retTing.val[c] nTotalTing = nTotalTing + 1 end
					end
					i = i + 1
				until i > j
				j = j + 1
			until j > m	
			m = m + 1
		until m > n
		n = n + 1
	until n > CONST.MAX_INDEX
	tingTotal.nTotalTing = nTotalTing
	return tingTotal
end
